package chapter02.part03;

import chapter02.FileUtil;

import java.io.*;

/**
 * 使用 readResolve() 保证单例和遗留枚举代码的序列化等同性
 * 
 * @author insight
 * @since 2021/8/16
 */
public class ReadSolve {
    public static void main(String[] args) throws IOException,
            ClassNotFoundException {
        // 正常情况下 单例和枚举(旧代码) 应当保证对象的等同性
        // 比如
        SingleTest instance = SingleTest.getInstance();
        // true
        System.out.println(instance == SingleTest.getInstance());
        
        // 问题/场景:
        // 但是由于 readObject() 返回新对象
        // 导致等同性失效
        ObjectOutputStream out =
                new ObjectOutputStream(FileUtil.getTestFileOutputStreamInstance());
        ObjectInputStream in =
                new ObjectInputStream(FileUtil.getTestFileInputStreamInstance());
        
        out.writeObject(instance);
        SingleTest newInstance = (SingleTest) in.readObject();
        // false
        System.out.println(newInstance == instance);
        
        // 方案: 使用 readResolve()
        Orientation h = Orientation.H;
        out.writeObject(h);
        Orientation newH = (Orientation) in.readObject();
        // true
        System.out.println(newH == h);

        out.close();
        in.close();
    }

    private static class SingleTest implements Serializable {
        private static SingleTest instance;
        
        private SingleTest() {}
        
        public static SingleTest getInstance() {
            if (instance == null) {
                instance = new SingleTest();
            }
            return instance;
        }
    }
    
    private static class Orientation implements Serializable {
        public static final Orientation H = new Orientation(1);
        public static final Orientation V = new Orientation(2);
        
        
        private int value;
        
        private Orientation(int v) { value = v; }

        /**
         * 序列化后会调用该方法
         */
        protected Object readResolve() throws InvalidObjectException {
            if (value == H.value) return H;
            if (value == V.value) return V;
            throw new InvalidObjectException("");
        }
    }
}